package com.example.multinetty.netty.thirdprotocal;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * netty服务端入门
 * 
 * @author -琴兽-
 * 
 */
@Component
@Slf4j
public class ChatServerFromNettyIOT implements ApplicationRunner {
	@Autowired
	private ServerHandler serverHandler;

	@Override
	public void run(ApplicationArguments args) throws Exception {
		start();
	}
	/**
	 * 启动
	 */
	public void start() {

		//如果是多个不同的协议，应让它对应不同的端口。如果同一个端口绑定不同的协议，必然会存在SocketChannel的缓存公用。这个时候会出现粘包，混包的出现
		//不同的端口起不同的协议，那么就在一个进程中启动不同的服务器实例，每个服务类实例绑定不同的端口，我感觉就应该可以实现单进程的多协议的服务器了。
		// 服务类
		ServerBootstrap b = new ServerBootstrap();

		// 创建boss和worker
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();

		try {
			// 设置循环线程组事例
			b.group(bossGroup, workerGroup);

			// 设置channel工厂
			b.channel(NioServerSocketChannel.class);

			// 设置管道
			b.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {

					//根据ch17章中的内容，定义了这几个参数。这个长度，仅仅是消息体的长度。
					ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024*1024,8,4));
					ch.pipeline().addLast(new FullRequestParse());

					ch.pipeline().addLast(new ResponseEncoder());
					ch.pipeline().addLast(serverHandler);
				}
			});

			b.option(ChannelOption.SO_BACKLOG, 2048);// 链接缓冲池队列大小

			// 绑定端口
			b.bind(10102).sync();

			System.out.println("start!!!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
